from typing import Optional, List
from datetime import datetime

from fastapi import HTTPException

from pydantic import BaseModel, field_validator


class Weather_record(BaseModel):
    id: int
    regionId: int
    temperature: float
    humidity: float
    windSpeed: float
    weatherCondition: str
    precipitationAmount: float
    measurementDateTime: datetime


class Weather_response(Weather_record):
    weatherForecast: List[int]


class Weather_response_with_region_name(Weather_response):
    regionName: str


class Weather_to_sql(BaseModel):
    regionId: Optional[int]
    temperature: float
    humidity: float
    windSpeed: float
    weatherCondition: str
    precipitationAmount: float
    measurementDateTime: datetime


class Upload_weather(Weather_to_sql):
    measurementDateTime: str
    weatherForecast: List[int]

    @field_validator('regionId')
    @classmethod
    def validate_regionId(cls, regionId: Optional[int]):
        if regionId is None or regionId <= 0:
            raise HTTPException(status_code=400, detail="bad regionId")
        return regionId

    @field_validator('measurementDateTime')
    @classmethod
    def validate_measurementDateTime(cls, measurementDateTime: str | datetime):
        if not (type(measurementDateTime) is str):
            return measurementDateTime
        try:
            datetime.fromisoformat(measurementDateTime)
        except Exception:
            raise HTTPException(status_code=400, detail="bad datetime")
        return measurementDateTime

    @field_validator('windSpeed')
    @classmethod
    def validate_windSpeed(cls, windSpeed: float):
        if windSpeed < 0:
            raise HTTPException(
                status_code=400,
                detail="bad windSpeed"
            )
        return windSpeed

    @field_validator('precipitationAmount')
    @classmethod
    def validate_precipitationAmount(cls, precipitationAmount: float):
        if precipitationAmount < 0:
            raise HTTPException(
                status_code=400,
                detail="bad precipitationAmount"
            )
        return precipitationAmount


class Update_weather(BaseModel):
    regionName: str
    temperature: float
    humidity: float
    windSpeed: float
    weatherCondition: str
    precipitationAmount: float
    measurementDateTime: datetime
    weatherForecast: List[int]

    @field_validator('measurementDateTime')
    @classmethod
    def validate_measurementDateTime(cls, measurementDateTime: str):
        if type(measurementDateTime) is datetime:
            return measurementDateTime
        try:
            datetime.fromisoformat(measurementDateTime)
        except Exception:
            raise HTTPException(status_code=400, detail="bad datetime")
        return measurementDateTime

    @field_validator('windSpeed')
    @classmethod
    def validate_windSpeed(cls, windSpeed: float):
        if windSpeed < 0:
            raise HTTPException(
                status_code=400,
                detail="bad windSpeed"
            )
        return windSpeed

    @field_validator('precipitationAmount')
    @classmethod
    def validate_precipitationAmount(cls, precipitationAmount: float):
        if precipitationAmount < 0:
            raise HTTPException(
                status_code=400,
                detail="bad precipitationAmount"
            )
        return precipitationAmount


class weatherCondition(BaseModel):
    id: int
    condition: str


class Weather_to_forecast_schema(BaseModel):
    id: int
    weatherId: int
    weatherForecast: int
